﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;


namespace Dwarf.Managed
{
    /// <summary>Solve the Pattern Search Problem by FSM with TPL parallelization</summary>
    ///
    class Solver
    {
        private Configurator dwarfConfigurator;             // processed settings from command line
        private List<int> positions;                        // search result
        private int contentPartCount = 0;

        /// <summary>Construct the new solver</summary>
        /// <param name="dwarfConfigurator">Processed command line arguments</param>
        /// 
        public Solver(ref Configurator dwarfConfigurator)
        {
            this.dwarfConfigurator = dwarfConfigurator;
            dwarfConfigurator.WriteSettings();               // write settings to console and profile file
        }

        /// <summary>TPL-parallelized method Pattern Search Problem by FSM method</summary>
        ///
        public void Solve()
        {
            string pattern = null;
            int[,] states = null;
            positions = new List<int>();
            int previousContentPosition = 0;                                        // new list of founded positions

            contentPartCount = dwarfConfigurator.GetData(ref pattern, dwarfConfigurator.GetThreadCount());  // get pattern from inputfile and evaluate the content part count           
            FiniteStateMachineBaseMethod.ConstructStates(ref states, pattern);      // create state array 

            Parallel.For(0, contentPartCount, i =>			// TPL directive
            {
                FiniteStateMachineBaseMethod fsmMethod;
                string contentPart;
                lock (states) {
                    contentPart = dwarfConfigurator.GetNextInputPart();                    
                }

                fsmMethod = new FiniteStateMachineBaseMethod(pattern, states, previousContentPosition, contentPart);
                int contentPartLength = contentPart.Length - contentPart[contentPart.Length - 1] - 1;
                fsmMethod.SetContentLength(contentPartLength);
                previousContentPosition += contentPartLength;

                fsmMethod.Solve();                          // Call solver for each content string part

                lock (positions) {
                    positions.AddRange(fsmMethod.GetPositionsList());
                }
            });

            positions.Sort();
        }

        /// <summary>Problem results output</summary>
        /// <param name="time">Spent time</param>
        ///
        public void Finish(double time)
        {
            dwarfConfigurator.Close(time, positions);
            Console.WriteLine("Total count of pattern entries: " + positions.Count);           // write all the positions count (all positions will be written into the output file)   
        }
    }
}

